package com.example.kingdeescan.ui.scan;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.kingdeescan.MainActivity;
import com.example.kingdeescan.R;
import com.example.kingdeescan.R2;
import com.example.kingdeescan.adapter.ScanResultNewAdapter;
import com.example.kingdeescan.dao.SEOutStock;
import com.example.kingdeescan.dao.SEOutStockEntry;
import com.example.kingdeescan.dto.DocInfoDTO;
import com.example.kingdeescan.dto.EncapsulateDTO;
import com.example.kingdeescan.dto.SSCEntryDTO;
import com.example.kingdeescan.dto.SSCHeadDTO;
import com.example.kingdeescan.dto.ScanResultDTO;
import com.example.kingdeescan.enums.CommitType;
import com.example.kingdeescan.enums.DialogType;
import com.example.kingdeescan.enums.DocType;
import com.example.kingdeescan.enums.MessageType;
import com.example.kingdeescan.utils.CustomDialog;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;

import java.io.Serializable;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import lombok.SneakyThrows;

import static com.example.kingdeescan.MainActivity.dbConfig;
import static com.example.kingdeescan.MainActivity.dbUtil;
import static com.example.kingdeescan.MainActivity.docInfoDTO;
import static com.example.kingdeescan.MainActivity.fragmentService;

/**
 * @author  : 2020/7/24
 * @date    : zly
 * @desc    : 扫码Fragment
 */
public class ScanFragment extends Fragment implements View.OnClickListener{
    public static final String TAG="ScanFragment";
    ScanViewModel scanViewModel;

    @BindView(R2.id.scan_edit)
    EditText mEditText;//扫码编辑框
    @BindView(R2.id.scan_result)
    TextView mScanTV;//扫码结果
    @BindView(R2.id.scanResultListView)
    ListView lv_scanResult;//扫码列表
    @BindView(R2.id.chb_select_way_point)
    @Nullable
    CheckBox checkBox;//扫码列表项中的CheckBox
    @BindView(R2.id.ll_edit_bar)
    @Nullable
    LinearLayout mLlEditBar;//控制底部编辑栏的显示与隐藏
    @Nullable
    TextView dialogText;//对话框提示文本
    @Nullable
    TextView dialogCancel;//对话框取消文本
    @Nullable
    TextView dialogSure;//对话框确认文本
    @BindView(R2.id.ll_cancel)
    @Nullable
    LinearLayout ll_cancel;//底部编辑框取消
    @BindView(R2.id.ll_delete)
    @Nullable
    LinearLayout ll_delete;//底部编辑框删除
    @BindView(R2.id.ll_inverse)
    @Nullable
    LinearLayout ll_inverse;//底部编辑框反选
    @BindView(R2.id.ll_select_all)
    @Nullable
    LinearLayout ll_select_all;//底部编辑框全选
    @BindView(R2.id.fab_commit)
    FloatingActionButton fab_commit;//提交悬浮按钮

    //存储扫码列表(用LinkedList实现，增删效率高)
    private List<ScanResultDTO> scanResultDTOList = new LinkedList<>();
    //存储扫码列表选中项(用LinkedList实现，增删效率高)
    private List<ScanResultDTO> scanResultDTOCheckedList = new LinkedList<>();
    //扫码列表适配器
    ScanResultNewAdapter scanResultNewAdapter;
    //自定义Dialog对话框
    private CustomDialog customDialog;
    //用来存放CheckBox的选中状态，true为选中,false为没有选中.(存储形式为键值对)
    private SparseBooleanArray stateCheckedMap = new SparseBooleanArray();
    //用来控制点击全选，全选和全不选相互切换
    private boolean isSelectedAll = true;

    //提交至服务器数据库的状态，默认为false,成功为true
    private AtomicBoolean insertStatus= new AtomicBoolean(false);
    //最大单据内码
    private int fInterID_Max=0;
    //最大销售出库单据体编号
    private int ssc_fEntryID_Max=0;
    //存储泛型单据对象
    private EncapsulateDTO<?> encapsulateDTO;

    Unbinder unbinder;//绑定ButterKnife视图

    //处理消息Handler
    Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what)
            {
                case MessageType.MESSAGE_COMMIT_ALL_SUCCESS:
                    Serializable validList = msg.getData().getSerializable("validList");
                    List<ScanResultDTO> validScanResultDTOList= (List<ScanResultDTO>) validList;
                    //移除所有校验通过的扫码对象
                    scanResultDTOList.removeAll(validScanResultDTOList);
                    scanResultNewAdapter.notifyDataSetChanged();//刷新适配器(刷新列表)
                    break;
                case MessageType.MESSAGE_COMMIT_SELECTED_SUCCESS:
                    Serializable validCheckedList = msg.getData().getSerializable("validCheckedList");
                    List<ScanResultDTO> validScanResultCheckedDTOList= (List<ScanResultDTO>) validCheckedList;
                    //移除所有选中的校验通过的扫码对象
                    scanResultDTOList.removeAll(validScanResultCheckedDTOList);
                    cancel();
                    break;
                case MessageType.MESSAGE_SCAN_EDIT:
                    String scanResult = msg.getData().getString("scanResult");
                    mScanTV.setText(scanResult);//显示扫码结果
                    mEditText.setText("");//清空扫码编辑框
                    scanResultNewAdapter.notifyDataSetChanged();//刷新适配器(刷新列表)
                    break;
                case MessageType.MESSAGE_SCAN_INVALID:
                    mEditText.setText("");//清空扫码编辑框
                    break;
            }
        }
    };

    /**
     * 初始化视图
     * @param inflater
     * @param container
     * @param savedInstanceState
     * @return
     */
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_scan, container, false);
        //返回一个Unbinder值（进行解绑），注意这里的this不能使用getActivity()
        unbinder = ButterKnife.bind(this, root);
        //加载ViewModel
        scanViewModel =
                ViewModelProviders.of(getActivity()).get(ScanViewModel.class);
        //判断是否选择单据类型，若为空则返回
        boolean invalidDocTypeResult = fragmentService.validDocType(getActivity(), container,this, docInfoDTO.getDocType());
        if (!invalidDocTypeResult){
            return null;
        }
        //判断是否从RecoredFragment校验数据成功跳转过来
        if (!getBundle()){
            fragmentService.invalidInvokeFragment(getActivity(), container, this);
            Toast.makeText(getContext(), "请先录入信息!", Toast.LENGTH_SHORT).show();
        }
        //初始化相关组件
        initComponet();

        return root;
    }

    /**
     * 初始化相关组件
     */
    private void initComponet(){
        initData();//初始化数据
        setAdapter();//设置适配器
        setListViewListener();//设置列表视图相关的监听事件
        setObserveOnViewModel();//设置观察者对象，当有设置缓存时，才可以用观察者模式监视并更新，否则忽略
    }

    /**
     * 获取Bundle传输数据并更新控件内容
     *
     * @return
     */
    private boolean getBundle() {
        Bundle bundle = getArguments();
        if (null == bundle) {
            return false;
        }
        int recoredStatus = bundle.getInt("RecoredStatus");
        if (200==recoredStatus){
            return true;
        }
        return  false;
    }

    /**
     * 设置适配器
     */
    private void setAdapter(){
        scanResultNewAdapter=new ScanResultNewAdapter(getContext(),R.layout.result_item, scanResultDTOList,stateCheckedMap);
        lv_scanResult.setAdapter(scanResultNewAdapter);
    }

    /**
     * 设置列表视图相关的监听事件
     */
    private void setListViewListener(){
        /**
         * 列表项单击更改CheckBox的选中状态
         */
        lv_scanResult.setOnItemClickListener((parent, view, position, id) -> {
            //实现只有出现底部编辑栏时，单击列表子项才响应事件
            if (mLlEditBar.getVisibility()==View.VISIBLE){
                updateCheckBoxStatus(view, position);
            }
        });
        /**
         * 列表项长按显示底部编辑栏
         * 如果返回false那么click仍然会被调用,,先调用Long click，然后调用click。
         * 如果返回true那么click就会被吃掉，click就不会再被调用了
         * 在这里click即setOnItemClickListener
         */
        lv_scanResult.setOnItemLongClickListener((parent, view, position, id) -> {
            mLlEditBar.setVisibility(View.VISIBLE);//显示下方布局
            scanResultNewAdapter.setShowCheckBox(true);//显示列表子项的CheckBox
            updateCheckBoxStatus(view, position);

            return true;
        });
        /**
         * 设置底部编辑栏的监听事件
         */
        ll_cancel.setOnClickListener(this);
        ll_delete.setOnClickListener(this);
        ll_inverse.setOnClickListener(this);
        ll_select_all.setOnClickListener(this);
        //添加编辑框文本更变监听器
        mEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                if (s.length()==0){//清空编辑框后，不进行处理
                    return;
                }
                final String barcode=s.toString();
                boolean scanResult=setScanResult(barcode);
                if (scanResult==false){
                    Message message=new Message();
                    message.what= MessageType.MESSAGE_SCAN_INVALID;
                    handler.sendMessage(message);

                    Toast.makeText(getContext(),"请正确扫码!",Toast.LENGTH_SHORT).show();
                    return;
                }
                Message message=new Message();
                message.what= MessageType.MESSAGE_SCAN_EDIT;
                Bundle data = new Bundle();
                data.putString("scanResult", barcode);
                message.setData(data);
                handler.sendMessage(message);
            }
        });
        //悬浮提交按钮单击
        fab_commit.setOnClickListener(this);
    }

    /**
     * 设置观察者对象，当有设置缓存时，才可以用观察者模式监视并更新，否则忽略
     */
    private void setObserveOnViewModel(){
        scanViewModel.getmScanResultText()
                .observe(this, s -> mScanTV.setText(s));//扫码结果
        scanViewModel.getScanResultDTOListMLD()
                .observe(this, scanResultDTOS -> {
                    scanResultDTOList=scanResultDTOS;
                    setAdapter();//设置适配器，显示扫码列表数据，若不设置，无法加载适配器
                });//扫码列表
        scanViewModel.getScanResultDTOCheckedListMLD()
                .observe(this, scanResultDTOS -> scanResultDTOCheckedList=scanResultDTOS);//扫码列表选中项
    }

    /**
     * 更改CheckBox状态
     * @param view
     * @param position
     */
    private void updateCheckBoxStatus(View view, int position) {
        ScanResultNewAdapter.ViewHolderInner holder = (ScanResultNewAdapter.ViewHolderInner) view.getTag();
        holder.checkBox.toggle();//反转CheckBox的选中状态
        lv_scanResult.setItemChecked(position, holder.checkBox.isChecked());//长按ListView时选中按的那一项
        stateCheckedMap.put(position, holder.checkBox.isChecked());//存放CheckBox的选中状态
        if (holder.checkBox.isChecked()) {
            scanResultDTOCheckedList.add(scanResultDTOList.get(position));//CheckBox选中时，把这一项的数据加到选中数据列表
        } else {
            scanResultDTOCheckedList.remove(scanResultDTOList.get(position));//CheckBox未选中时，把这一项的数据从选中数据列表移除
        }
        scanResultNewAdapter.notifyDataSetChanged();
    }

    /**
     * 初始化数据
     */
    private void initData(){
        scanResultDTOList.add(new ScanResultDTO("1.0.01",100));
        scanResultDTOList.add(new ScanResultDTO("00.06.F0382",90));
        scanResultDTOList.add(new ScanResultDTO("1.0.03",80));
        scanResultDTOList.add(new ScanResultDTO("00.07.G0130",100));

        setStateCheckedMap(false);
    }

    /**
     * 取消
     */
    private void cancel() {
        setStateCheckedMap(false);//将CheckBox的所有选中状态变成未选中
        scanResultDTOCheckedList.clear();//清空选中列表
        mLlEditBar.setVisibility(View.GONE);//隐藏下方布局
        scanResultNewAdapter.setShowCheckBox(false);//让CheckBox那个方框隐藏
        scanResultNewAdapter.notifyDataSetChanged();//更新ListView
    }

    /**
     * 删除
     */
    private void delete() {
        if (scanResultDTOCheckedList.size() == 0) {
            Toast.makeText(getContext(), "您还没有选中任何数据！", Toast.LENGTH_SHORT).show();
            return;
        }
        //创建自定义对话框
        alertCustomDialog(getContext(),"确认删除?", DialogType.DIALOG_DELETE);
    }

    /**
     * 删除方法
     */
    private void beSureDelete() {
        scanResultDTOList.removeAll(scanResultDTOCheckedList);//删除选中数据
        cancel();
        Toast.makeText(getContext(), "删除成功", Toast.LENGTH_SHORT).show();
    }

    /**
     * 反选就是stateCheckedMap的值为true时变为false,false时变成true
     * */
    private void inverse() {
        scanResultDTOCheckedList.clear();
        for (int i = 0; i < scanResultDTOList.size(); i++) {
            if (stateCheckedMap.get(i)) {
                stateCheckedMap.put(i, false);
            } else {
                stateCheckedMap.put(i, true);
                scanResultDTOCheckedList.add(scanResultDTOList.get(i));
            }
            lv_scanResult.setItemChecked(i, stateCheckedMap.get(i));//这个可以控制ListView复用的问题，不设置这个会出现点击一个会选中多个
        }
        scanResultNewAdapter.notifyDataSetChanged();//刷新适配器
    }

    /**
     * 全选
     */
    private void selectAll() {
        scanResultDTOCheckedList.clear();//清空选中数据
        if (isSelectedAll) {
            setStateCheckedMap(true);//将CheckBox的所有选中状态变成选中
            isSelectedAll = false;
            scanResultDTOCheckedList.addAll(scanResultDTOList);//把所有的数据添加到选中列表中
        } else {
            setStateCheckedMap(false);//将CheckBox的所有选中状态变成未选中
            isSelectedAll = true;
        }
        scanResultNewAdapter.notifyDataSetChanged();
    }

    /**
     * 设置所有CheckBox的选中状态
     * @param isSelectedAll
     */
    private void setStateCheckedMap(boolean isSelectedAll) {
        for (int i = 0; i < scanResultDTOList.size(); i++) {
            stateCheckedMap.put(i, isSelectedAll);
            lv_scanResult.setItemChecked(i, isSelectedAll);
        }
    }

    /**
     * 监听单击事件
     * @param v
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.ll_cancel:
                cancel();
                break;
            case R.id.ll_delete:
                delete();
                break;
            case R.id.ll_inverse:
                inverse();
                break;
            case R.id.ll_select_all:
                selectAll();
                break;
            case R.id.dialog_cancel:
                cancel();
                customDialog.dismiss();
                break;
            case R.id.dialog_sure:
                //根据CustomDialog的成员变量dialogCode作出不同的上下文响应
                switch (customDialog.dialogType){
                    case DIALOG_DELETE:
                        //删除对话框的确定
                        beSureDelete();
                        customDialog.dismiss();
                        break;
                    case DIALOG_COMMIT:
                        if (dialogText.getText().toString().equals("确认全部提交？")){
                            int commitAllStatus = commit(CommitType.COMMIT_ALL);
                            switch (commitAllStatus){
                                case CommitType.COMMIT_ALL_INVALID:
                                    Toast.makeText(getContext(), "未在选单号中匹配到有效的物料!", Toast.LENGTH_SHORT).show();
                                    break;
                                case CommitType.COMMIT_DBS_FAIL:
                                    Toast.makeText(getContext(), "提交失败，参数异常!", Toast.LENGTH_SHORT).show();
                                    break;
                                case CommitType.COMMIT_DBS_SUCCESS:
                                    Toast.makeText(getContext(), "提交成功!", Toast.LENGTH_SHORT).show();
                                    break;
                            }
                        }
                        if (dialogText.getText().toString().equals("确认提交选中数据？")){
                            int commitSelectedStatus = commit(CommitType.COMMIT_SELECTED);
                            switch (commitSelectedStatus){
                                case CommitType.COMMIT_ALL_INVALID:
                                    cancel();
                                    Toast.makeText(getContext(), "未在选单号中匹配到选中的有效的物料!", Toast.LENGTH_SHORT).show();
                                    break;
                                case CommitType.COMMIT_DBS_FAIL:
                                    cancel();
                                    Toast.makeText(getContext(), "选中数据提交失败，参数异常!", Toast.LENGTH_SHORT).show();
                                    break;
                                case CommitType.COMMIT_DBS_SUCCESS:
                                    Toast.makeText(getContext(), "选中数据提交成功!", Toast.LENGTH_SHORT).show();
                                    break;
                            }
                        }
                        customDialog.dismiss();
                        break;
                }
                break;
            case R.id.fab_commit://悬浮提交按钮
                commitChecked();//提交检查
                break;
        }
    }

    /**
     * 提交方法
     */
    private void commitChecked() {
        //检查列表是否存在数据
        if (scanResultDTOList.size()<=0){
            Toast.makeText(getContext(),"暂无数据，请扫码！",Toast.LENGTH_SHORT).show();
            return;
        }
        //检查列表是否选中
        if (scanResultDTOCheckedList.size()<=0){
            //当全部都没有选中，即默认全部提交，优化用户操作
            //创建对话框
            alertCustomDialog(getContext(),"确认全部提交？",DialogType.DIALOG_COMMIT);
        }else{
            //有选中，即用户希望提交选中的数据
            //创建对话框
            alertCustomDialog(getContext(),"确认提交选中数据？",DialogType.DIALOG_COMMIT);
        }
    }

    /**
     * 提交数据至数据库
     * @param commitType
     *      提交状态码
     * @return
     *      操作结果状态码
     *          CommitType.COMMIT_ALL_INVALID：扫码对象全部校验失败
     *          COMMIT_DBS_FAIL:单据提交服务器失败
     *          CommitType.COMMIT_DBS_SUCCESS：校验成功，提交至服务器成功，更新扫码列表，保留未成功校验或提交的扫码对象
     */
    private int commit(int commitType){
        int commitStatus=CommitType.COMMIT_ALL_INVALID;//默认为扫码对象全部校验失败

        //根据所选单据类型封装相应列表项数据至单据实体类
        switch (commitType){
            case CommitType.COMMIT_ALL:
                //获取校验返回的泛型集合validScanResultDTOList
                List<ScanResultDTO> validScanResultDTOList = validData(docInfoDTO, this.scanResultDTOList);
                //若validScanResultDTOList>0，则说明有数据通过校验；若<0，则说明数据全部没校验成功
                if (validScanResultDTOList.size()>0){
                    //判断泛型单据是否存在
                    if (null!=encapsulateDTO){
                        commitToDBS(docInfoDTO,encapsulateDTO);
                        if (insertStatus.get()){
                            //提交服务器成功，则更新扫码列表视图，移除校验成功的扫码对象
                            Message message=new Message();
                            message.what=MessageType.MESSAGE_COMMIT_ALL_SUCCESS;
                            Bundle bundle=new Bundle();
                            bundle.putSerializable("validList", (Serializable) validScanResultDTOList);
                            message.setData(bundle);
                            handler.sendMessage(message);

                            commitStatus=CommitType.COMMIT_DBS_SUCCESS;
                        }else{
                            commitStatus=CommitType.COMMIT_DBS_FAIL;
                        }
                    }
                }
                break;
            case CommitType.COMMIT_SELECTED:
                //获取校验返回的泛型集合validScanResultDTOCheckedList
                List<ScanResultDTO> validScanResultDTOCheckedList = validData(docInfoDTO,scanResultDTOCheckedList);
                //若validScanResultDTOCheckedList>0，则说明有数据通过校验；若<0，则说明数据全部没校验成功
                if (validScanResultDTOCheckedList.size()>0){
                    //判断泛型单据是否存在
                    if (null!=encapsulateDTO){
                        commitToDBS(docInfoDTO,encapsulateDTO);
                        if (insertStatus.get()){
                            //提交服务器成功，则更新扫码列表视图，移除校验成功的扫码对象
                            Message message=new Message();
                            message.what=MessageType.MESSAGE_COMMIT_SELECTED_SUCCESS;
                            Bundle bundle=new Bundle();
                            bundle.putSerializable("validCheckedList", (Serializable) validScanResultDTOCheckedList);
                            message.setData(bundle);
                            handler.sendMessage(message);

                            commitStatus=CommitType.COMMIT_DBS_SUCCESS;
                        }else{
                            commitStatus=CommitType.COMMIT_DBS_FAIL;
                        }
                    }
                }
                break;
        }

        return commitStatus;
    }

    /**
     * 校验数据并封装单据
     * @param docInfoDTO
     *      单据信息对象
     * @param resultDTOList
     *      扫码结果对象集合
     * @return
     *      返回校验通过的泛型数据集合validList
     */
    private List<ScanResultDTO> validData(DocInfoDTO docInfoDTO, List<ScanResultDTO> resultDTOList){
        //存储校验成功的物料代码数据
        List<ScanResultDTO> validSRDTOList=new LinkedList<>();
        encapsulateSSCKNull://若封装销售出库单据头出现异常为null，则跳出多重循环的标记

        //销售出库单
        if (docInfoDTO.getDocType()== DocType.DOC_TYPE_SSCK){
            //存储销售出库单据集合
            List<SSCEntryDTO> sscEntryDTOList=new LinkedList<>();
            SSCHeadDTO sscHeadDTO = null;

            //遍历扫码结果集合，判断是否存在
            for (int k = 0; k < resultDTOList.size(); k++) {
                ScanResultDTO scanResultDTO = resultDTOList.get(k);//扫码结果对象
                //遍历选单号集合
                breakPoint: for (int i = 0; i < MainActivity.docInfoDTO.getSelectedList().size(); i++) {
                    //将泛型强转成发货通知单类型集合
                    List<SEOutStock> seOutStockList = (List<SEOutStock>) MainActivity.docInfoDTO.getSelectedList();
                    SEOutStock seOutStock = seOutStockList.get(i);//获取发货通知单
                    //封装销售出库单据头
                    sscHeadDTO = encapsulateSSCKHead(MainActivity.docInfoDTO, seOutStock);
                    //若封装失败，则跳出多重循环
                    if (null==sscHeadDTO){
                        break encapsulateSSCKNull;
                    }
                    //获取发货通知单分录集合
                    List<SEOutStockEntry> seOutStockEntryList = seOutStock.getSeOutStockEntryList();
                    //遍历发货通知单分录集合
                    for (int j = 0; j < seOutStockEntryList.size(); j++) {
                        SEOutStockEntry seOutStockEntry = seOutStockEntryList.get(j);//获取发货通知单分录对象
                        //若成功匹配，则添加到校验成功的validSRDTOList中
                        if (seOutStockEntry.getFItemNumber().equals(scanResultDTO.getWldm())){
                            //封装销售出库单据体
                            SSCEntryDTO sscEntryDTO = encapsulateSSCKEntry(sscHeadDTO,seOutStockEntry, scanResultDTO);
                            //成功封装则不为空
                            if (null==sscEntryDTO){
                                break encapsulateSSCKNull;
                            }
                            //添加至销售出库单据集合
                            sscEntryDTOList.add(sscEntryDTO);
                            //添加至校验成功的扫码结果对象集合
                            validSRDTOList.add(scanResultDTO);
                            break breakPoint;
                        }
                    }
                }
            }

            Objects.requireNonNull(sscHeadDTO).setSscEntryDTOList(sscEntryDTOList);//将销售出库单据体集合封装
            encapsulateDTO=new EncapsulateDTO<>(sscHeadDTO);//存储销售出库单据
        }

        //返回校验通过的数据对象集合
        return validSRDTOList;
    }

    /**
     * 封装销售出库单据头
     * @param docInfoDTO
     * @param stock
     * @return
     */
    private SSCHeadDTO encapsulateSSCKHead(DocInfoDTO docInfoDTO, SEOutStock stock){
        try {
            Thread queryThread=new Thread(()->{
                //查询销售出库单据头的内码
                try {
                    fInterID_Max = dbUtil.queryMaxFInterID(docInfoDTO);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            queryThread.start();
            queryThread.join();

            if (fInterID_Max==0){
                return null;
            }

            //封装销售出库单据头数据
            SSCHeadDTO sscHeadDTO=new SSCHeadDTO();
            sscHeadDTO.setFBrNo("0");
            sscHeadDTO.setFInterID(fInterID_Max+1);
            sscHeadDTO.setFTranType(21);
            sscHeadDTO.setFBillNo(docInfoDTO.getFBillno());
            sscHeadDTO.setFDeptID(docInfoDTO.getFDept().getFItemID());
            sscHeadDTO.setFEmpID(docInfoDTO.getFEmp().getFItemID());
            sscHeadDTO.setFFManagerID(docInfoDTO.getFfManger().getFItemID());
            sscHeadDTO.setFBillerID(docInfoDTO.getFBiller().getFUserID());
            sscHeadDTO.setFSupplyID(docInfoDTO.getFOrg().getFItemID());
            sscHeadDTO.setFHeadSelfB0164(stock.getFHeadSelfS0238());//客户单号

            return sscHeadDTO;
        }catch (Exception e){
            return null;
        }
    }

    /**
     * 封装销售出库单据体
     * @param stockEntry
     * @param resultDTO
     * @return
     */
    private SSCEntryDTO encapsulateSSCKEntry(SSCHeadDTO sscHeadDTO,SEOutStockEntry stockEntry, ScanResultDTO resultDTO){
        try {
            float newQty=stockEntry.getFAuxQty()+resultDTO.getQuantity();
            //封装销售出库单据体数据
            SSCEntryDTO sscEntryDTO=new SSCEntryDTO();
            sscEntryDTO.setFBrNo("0");
            sscEntryDTO.setFInterID(sscHeadDTO.getFInterID());
//            sscEntryDTO.setFEntryID(ssc_fEntryID_Max);
            sscEntryDTO.setFItemID(stockEntry.getFItemID());
            sscEntryDTO.setFQtyMust(newQty);
            sscEntryDTO.setFQty(newQty);
            sscEntryDTO.setFPrice(stockEntry.getFPrice());
            sscEntryDTO.setFAmount(stockEntry.getFAmount());
            sscEntryDTO.setFUnitID(stockEntry.getFUnitID());
            sscEntryDTO.setFAuxPrice(stockEntry.getFPrice());
            sscEntryDTO.setFAuxQty(newQty);
            sscEntryDTO.setFAuxQtyMust(newQty);
//            sscEntryDTO.setFSourceEntryID(ssc_fEntryID_Max);
            sscEntryDTO.setFAuxPropID(stockEntry.getFAuxPropID());
            sscEntryDTO.setFSourceTranType(21);
            sscEntryDTO.setFSourceInterId(sscHeadDTO.getFInterID());
            sscEntryDTO.setFSourceBillNo(sscHeadDTO.getFBillNo());
            sscEntryDTO.setFClientOrderNo(sscHeadDTO.getFHeadSelfB0164());

            return sscEntryDTO;
        }catch (Exception e){
            return null;
        }
    }

    /**
     * 提交单据至服务器数据库
     * @param docInfoDTO
     * @param encapsulateDTO
     * @param <T>
     */
    @SneakyThrows
    private <T> void commitToDBS(DocInfoDTO docInfoDTO,EncapsulateDTO<T> encapsulateDTO){
        Thread insertThread;
        //销售出库单
        if (docInfoDTO.getDocType()== DocType.DOC_TYPE_SSCK) {
            if (null==encapsulateDTO){
                insertStatus.set(false);
            }else{
                insertThread=new Thread(()-> {
                    try {
                        insertStatus.set(dbUtil.insertSSCK((SSCHeadDTO) encapsulateDTO.getT()));
                    }catch (Exception e){
                        e.printStackTrace();
                        insertStatus.set(false);
                    }
                });
                insertThread.start();
                insertThread.join();
            }
        }
    }

    /**
     * 弹出自定义Dialog
     * @param context
     */
    private void alertCustomDialog(Context context, CharSequence dialogTitle, DialogType dialogType){
        //加载自定义Dialog类
        customDialog=new CustomDialog(context,R.layout.dialog_layout,new int[]{
                R.id.dialog_cancel,R.id.dialog_sure
        },dialogType);
        //显示Dialog
        customDialog.show();
        //获取控件
        dialogText=customDialog.findViewById(R.id.dialog_text);
        dialogCancel=customDialog.findViewById(R.id.dialog_cancel);
        dialogSure=customDialog.findViewById(R.id.dialog_sure);
        //设置Dialog的显示图标
        Drawable drawable;
        switch (dialogType){
            case DIALOG_DELETE:
                drawable= getResources().getDrawable(R.drawable.ic_delete);
                drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
                dialogText.setCompoundDrawables(drawable,null,null,null);
                break;
            case DIALOG_COMMIT:
                drawable= getResources().getDrawable(R.drawable.ic_commit);
                drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
                dialogText.setCompoundDrawables(drawable,null,null,null);
                break;
        }
        //设置Dialog的显示文本
        dialogText.setText(dialogTitle);
        dialogCancel.setOnClickListener(this);
        dialogSure.setOnClickListener(this);
    }

    /**
     * 获取扫码返回值并更新列表
     * @param barcode
     * @return
     */
    private boolean setScanResult(String barcode){
        if ("".equals(barcode)) {
            return false;
        }
        //提取物料代码和数量
        String[] split = barcode.split("/");
        //非有效扫码数据
        if (split.length<=1){
            return false;
        }
        String newWldm=split[0];
        Integer newQuantity=Integer.parseInt(split[1]);
        //若当前物料已存在，则累加数量；否则新增物料
        int index = isWLDMExists(newWldm);
        if (-1==index){
            //将扫码结果添加到列表中
            scanResultDTOList.add(new ScanResultDTO(newWldm,newQuantity));
        }else{
            ScanResultDTO scanResultDTO = scanResultDTOList.get(index);//获取指定索引出的ScanResultDTO对象
            int oldQuantity=scanResultDTO.getQuantity();//获取指定索引出的ScanResultDTO对象的数量
            scanResultDTO.setQuantity(oldQuantity+newQuantity);//更改数量
            scanResultDTOList.set(index,scanResultDTO);//在指定索引处重新设置ScanResultDTO对象
        }
        //对扫码列表进行排序，根据物料代码升序的规则
        Collections.sort(scanResultDTOList, (scanResultDTO1, scanResultDTO2) -> scanResultDTO1.getWldm().compareTo(scanResultDTO2.getWldm()));
        return true;
    }

    /**
     * 判断新物料是否存在
     * @param newWldm
     * @return
     *      物料的索引
     *      -1：不存在
     */
    private int isWLDMExists(String newWldm){
        for (int i = 0; i < scanResultDTOList.size(); i++) {
            if (newWldm.equals(scanResultDTOList.get(i).getWldm())){
                return i;
            }
        }
        return -1;
    }

    /**
     * 缓存数据至ViewModel
     */
    private void setScanViewModel(){
        if (null!= mScanTV){
            //存储扫码结果
            String s = mScanTV.getText().toString();
            scanViewModel.setmScanResultText(s);
        }
        //缓存扫码列表至ViewModel中
        scanViewModel.setScanResultDTOListMLD(scanResultDTOList);
        //缓存扫码列表选中项至ViewModel中
        scanViewModel.setScanResultDTOCheckedListMLD(scanResultDTOCheckedList);
    }

    /**
     * 缓存数据至ViewModel中
     */
    @Override
    public void onPause() {
        super.onPause();
        setScanViewModel();//缓存数据至ViewModel
    }

    /**
     * onDestroyView中进行
     *      解绑操作
     *      利用ViewModel存储数据
     */
    @SneakyThrows
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();//解绑butterknife视图
    }
}